import * as d3 from "d3-scale";
import { falseStr } from "./NotInHbMap";
const scaleLinear = d3.scaleLinear;

const lonNum = 321;
const lonMax = 116.25;
const lonSpan = 0.025000000000005684;
const latSpan = 0.02500000000000213;
const latMin = 28.9;
const lonMin = 108.25;
const latMax = 33.4;
const latNum = 181;

export const gridInfo = {
  lonNum: lonNum,
  lonMax: lonMax,
  lonSpan: lonSpan,
  latSpan: latSpan,
  latMin: latMin,
  lonMin: lonMin,
  latMax: latMax,
  latNum: latNum
};
export function parseColorAndValueArray(t) {
  const e = {
    colorArray: [],
    colorValArray: []
  };
  for (let a = 0; a < t.length; a += 1) {
    e.colorArray[a] = t[a].color.replace("rgb", "rgba").replace(")", ",0.3)");
    e.colorValArray[a] = t[a].min == null ? -1 / 0 : t[a].min;
    e.colorValArray[a] = t[a].val || t[a].min || t[a].max;
  }
  return e;
}
// 计算经纬度
function calcLonLats(t, e, a) {
  const i = [];
  for (let n = 0; n < a; n += 1) {
    i[n] = t + n * e;
  }
  return i;
}
// 转换接口数据
function transformatData(data, colorConfig) {
  //   const {
  //     gridData,
  //     gridInfo: { latMax, latMin, latSpan, latNum, lonNum, lonMin, lonSpan, lonMax }
  //   } = data;
  const { gridData } = data;

  //   gridInfo数据前端写死

  const lats = calcLonLats(latMin, latSpan, latNum).reverse();
  const lons = calcLonLats(lonMin, lonSpan, lonNum);
  //   const realGridData = gridData.reverse();
  const { colorArray, colorValArray } = parseColorAndValueArray(colorConfig);
  return {
    clipBoundary: null,
    gridData: {
      options: {
        gridHeader: {
          lonMin,
          lonMax,
          latMax: latMin,
          latMin: latMax,
          lonSpan,
          latSpan,
          lonNum,
          latNum,
          lats,
          lons
        },
        gridArray: gridData,
        invalidValue: [9999]
      },
      params: {
        gridHeader: {
          lonMin,
          lonMax,
          latMax: latMin,
          latMin: latMax,
          lonSpan,
          latSpan,
          lonNum,
          latNum,
          lats,
          lons
        },
        gridArray: gridData,
        invalidValue: [9999]
      }
    },
    colorArray: colorArray,
    colorValArray: colorValArray
  };
}
export default class Grid2Canvas {
  constructor({ map, data: options, colorConfig, canvasContainer: canvas }) {
    this._map = map;
    this._colorConfig = colorConfig;
    this.options = {};
    this.canvas = canvas || document.createElement("canvas");
    if (options.gridData) {
      this.setData(options);
    } else {
      return this;
    }
  }
  initCanvas() {
    // this.canvas.width = this._map.getCanvas().width;
    // this.canvas.height = this._map.getCanvas().height;
    this.canvas.width = 321;
    this.canvas.height = 181;
    var sw = new SGMap.LngLat(
      this.options.gridData.params.gridHeader.lonMin,
      this.options.gridData.params.gridHeader.latMax
    );
    var ne = new SGMap.LngLat(
      this.options.gridData.params.gridHeader.lonMax,
      this.options.gridData.params.gridHeader.latMin
    );
    this.gridLatLngBound = new SGMap.LngLatBounds(sw, ne);
    const zoom = this._map.getZoom();
    const params = {
      lats: this.options.gridData.params.gridHeader.lats,
      lons: this.options.gridData.params.gridHeader.lons,
      latNum: this.options.gridData.params.gridHeader.latNum,
      lonNum: this.options.gridData.params.gridHeader.lonNum,
      gridData: this.options.gridData.params.gridArray,
      lonSpan: this.options.gridData.params.gridHeader.lonSpan,
      latSpan: this.options.gridData.params.gridHeader.latSpan,
      invalid: this.options.gridData.params.invalidValue
    };
    const lonhalf = Math.abs(params.lonSpan) / 2;
    const lathalf = Math.abs(params.latSpan) / 2;
    const ctx = this.canvas.getContext("2d", { willReadFrequently: true });
    this.drawChoroplethicRect(zoom, params, lathalf, lonhalf, ctx);
  }
  drawUnit(e, a, i, n, s, o, r) {
    // console.log(a, i);
    e.fillStyle = o;
    e.fillRect(a, i, n + 1, s + 1);
    if (r) {
      e.strokeStyle = this.options.gridBorderColor;
      e.strokeRect(a, i, n + 1, s + 1);
    }
  }
  setData(data, colorConfig = this._colorConfig) {
    if (!data) return;
    this.options = transformatData(data, colorConfig);
    // console.log('this.options', this.options)
    this.update();
  }
  update() {
    this.initCanvas();
  }
  fillColor(val, colorArray, colorValArray) {
    // const color = null;
    colorValArray.length > 0 &&
      Number.isNaN(colorValArray[0]) &&
      (colorValArray[0] = -Infinity);
    // for (let i = colorValArray.length - 1; i >= 0; i -= 1) {
    //   if (val < colorValArray[0]) {
    //     color = "rgba(0,0,0,0)";
    //     break;
    //   }
    //   if (val >= colorValArray[i]) {
    //     color = colorArray[i];
    //     break;
    //   }
    // }
    if (val <= colorValArray[0]) {
      return "rgba(255, 255, 255,0)";
    } else {
      const crayons = scaleLinear().domain(colorValArray).range(colorArray);
      return crayons(val);
    }
  }
  isInvalidVal(t, e) {
    return Array.isArray(e) ? e.indexOf(t) > -1 : t === e;
  }
  drawChoroplethicRect(zoom, params, lathalf, lonhalf, ctx) {
    const falseArr = JSON.parse(falseStr);
    for (let r = 0; r < params.latNum; r += 1) {
      for (let a = 0; a < params.lonNum; a += 1) {
        if (this.isInvalidVal(params.gridData[r][a], params.invalid)) continue;
        let u = this.fillColor(
          params.gridData[r][a],
          this.options.colorArray,
          this.options.colorValArray
        );
        if (r > 174 || r < 6) {
          u = "transparent";
        } else {
          const list = falseArr[r];
          if (list.includes(`${a},${r}`)) {
            u = "transparent";
          }
        }
        this.drawUnit(ctx, a, r, 1, 1, u, false);
      }
    }
    // localStorage.setItem(Date.now(),this.canvas.]Url())
    this.bindEvent();
  }
  bindEvent() {
    var markerHeight = 50;
    var markerRadius = 10;
    var linearOffset = 25;
    var popupOffsets = {
      top: [0, 0],
      "top-left": [0, 0],
      "top-right": [0, 0],
      bottom: [0, -markerHeight],
      "bottom-left": [
        linearOffset,
        (markerHeight - markerRadius + linearOffset) * -1
      ],
      "bottom-right": [
        -linearOffset,
        (markerHeight - markerRadius + linearOffset) * -1
      ],
      left: [markerRadius, (markerHeight - markerRadius) * -1],
      right: [-markerRadius, (markerHeight - markerRadius) * -1]
    };
    this.canvas.addEventListener("click", event => {
      const a = this.findCanvasPosition(this.canvas);
      const i = event.pageX - a.x;
      const n = event.pageY - a.y;
      const r = this._map.unproject([i, n]);
      this.gridLatLngBound.contains(r) &&
        setTimeout(() => {
          const popup = new SGMap.Popup({
            offset: popupOffsets,
            className: "my-class"
          });
          popup
            .setLngLat(r)
            .setText(
              `${this.getGridVal(r, this.options.gridData)} ${this.options.unit || "℃"
              }`
            )
            .addTo(this._map);
        }, 100);
    });
  }
  // 获取点击位置的属性值
  getGridVal(t, e) {
    e = e || this.options.gridData;
    let a = e.params.gridHeader.latMax;
    let i = e.params.gridHeader.lonMin;
    const n = e.params.gridHeader.latSpan;
    const s = e.params.gridHeader.lonSpan;
    a += Math.abs(n) / 2;
    i -= Math.abs(s) / 2;
    const o = t.lat;
    const r = t.lng;
    const l = Math.ceil((o - a) / n) - 1;
    const d = Math.ceil((r - i) / s) - 1;
    return e.params.gridArray[l][d];
    // return l+','+d
  }
  findCanvasPosition(t) {
    let e = 0;
    let a = 0;
    if (t.offsetParent) {
      do {
        e += t.offsetLeft;
        a += t.offsetTop;
        t = t.offsetParent;
      } while (t);
      return {
        x: e,
        y: a
      };
    }
  }
}
